import { Injectable, Logger } from '@nestjs/common';
import { v4 as uuidv4 } from 'uuid';
import { 
  CreateMessageDto, 
  CountTokensDto,
  MessageResponseDto,
  CountTokensResponseDto
} from './dto/messages.dto';
import { ProxyConfigService, ProxyMode } from './config/proxy.config';
import { ForwardingService } from './services/forwarding.service';
import { 
  ListModelsQueryDto,
  ModelsResponseDto,
  ModelDto
} from './dto/models.dto';
import {
  CreateBatchDto,
  BatchResponseDto,
  ListBatchesQueryDto,
  BatchesResponseDto,
  GetBatchParamsDto
} from './dto/batches.dto';
import {
  UploadFileDto,
  FileResponseDto,
  ListFilesQueryDto,
  FilesResponseDto,
  DeleteFileResponseDto
} from './dto/files.dto';
import { AnthropicRequestLog } from './interfaces/anthropic-api.interface';
import { 
  mockMessagesResponse,
  mockMessagesWithThinkingResponse,
  mockMessagesWithToolUseResponse,
  mockCountTokensResponse,
  mockModels,
  mockModelsResponse,
  mockBatch,
  mockCompletedBatch,
  mockFiles,
  mockFilesResponse,
  AnthropicMockGenerator
} from './mock-data/anthropic-mock.data';

@Injectable()
export class AnthropicProxyService {
  private readonly logger = new Logger(AnthropicProxyService.name);
  private readonly requestLogs: AnthropicRequestLog[] = [];

  constructor(
    private readonly proxyConfigService: ProxyConfigService,
    private readonly forwardingService: ForwardingService
  ) {}

  // 注入配置管理服务（延迟注入避免循环依赖）
  private configManagementService: any;

  // Messages API Methods
  async createMessage(createMessageDto: CreateMessageDto, requestInfo: Partial<AnthropicRequestLog>): Promise<MessageResponseDto> {
    this.logRequest('POST', '/v1/messages', createMessageDto, requestInfo);

    const mode = this.proxyConfigService.getProxyMode();
    
    if (mode === ProxyMode.COPILOT) {
      // 使用转发服务
      this.logger.log(`Using Copilot forwarding mode for model: ${createMessageDto.model}`);
      const result = await this.forwardingService.forwardMessageRequest(createMessageDto, requestInfo);
      this.logger.debug('Service received response from ForwardingService:', JSON.stringify(result, null, 2));
      return result;
    } else {
      // 使用 Mock 模式
      this.logger.log(`Using Mock mode for model: ${createMessageDto.model}`);
      return await this.generateMockResponse(createMessageDto, requestInfo);
    }
  }

  // Mock 响应生成方法
  private async generateMockResponse(createMessageDto: CreateMessageDto, requestInfo: Partial<AnthropicRequestLog>): Promise<MessageResponseDto> {
    // 检查是否包含思考或工具使用
    const includeThinking = createMessageDto.thinking?.enabled || false;
    const includeToolUse = createMessageDto.tools && createMessageDto.tools.length > 0;

    // 从消息中提取文本内容用于生成响应
    const lastMessage = createMessageDto.messages[createMessageDto.messages.length - 1];
    let inputText = '';
    
    if (typeof lastMessage.content === 'string') {
      inputText = lastMessage.content;
    } else if (Array.isArray(lastMessage.content)) {
      inputText = lastMessage.content
        .filter(block => block.type === 'text')
        .map(block => block.text)
        .join(' ');
    }

    // 模拟处理延迟
    await this.simulateProcessingDelay();

    // 生成动态 Mock 响应
    const response = AnthropicMockGenerator.generateMessagesResponse(
      inputText, 
      createMessageDto.model,
      includeThinking,
      includeToolUse && inputText.includes('天气')
    );

    this.logger.log(`Generated mock response for model: ${createMessageDto.model}, input length: ${inputText.length}`);
    
    return response;
  }

  async countTokens(countTokensDto: CountTokensDto, requestInfo: Partial<AnthropicRequestLog>): Promise<CountTokensResponseDto> {
    this.logRequest('POST', '/v1/messages/count-tokens', countTokensDto, requestInfo);

    const mode = this.proxyConfigService.getProxyMode();
    
    if (mode === ProxyMode.COPILOT) {
      // 使用转发服务
      this.logger.log(`Using Copilot forwarding mode for token counting`);
      return await this.forwardingService.forwardCountTokensRequest(countTokensDto, requestInfo);
    } else {
      // 使用 Mock 模式
      this.logger.log(`Using Mock mode for token counting`);
      return this.generateMockTokenCount(countTokensDto);
    }
  }

  // Mock 令牌计数方法
  private generateMockTokenCount(countTokensDto: CountTokensDto): CountTokensResponseDto {
    // 计算输入令牌数（简单估算：字符数除以4）
    let totalText = '';
    
    // 从系统提示计算
    if (countTokensDto.system) {
      if (typeof countTokensDto.system === 'string') {
        totalText += countTokensDto.system;
      }
    }

    // 从消息计算
    countTokensDto.messages.forEach(message => {
      if (typeof message.content === 'string') {
        totalText += message.content;
      } else if (Array.isArray(message.content)) {
        totalText += message.content
          .filter(block => block.type === 'text')
          .map(block => block.text || '')
          .join(' ');
      }
    });

    const response = AnthropicMockGenerator.generateCountTokensResponse(totalText);
    
    this.logger.log(`Counted tokens for input text length: ${totalText.length}, estimated tokens: ${response.input_tokens}`);
    
    return response;
  }

  // Models API Methods
  async listModels(query: ListModelsQueryDto, requestInfo: Partial<AnthropicRequestLog>): Promise<ModelsResponseDto> {
    this.logRequest('GET', '/v1/models', null, requestInfo, query);

    // 模拟分页逻辑
    let models = [...mockModels];
    
    if (query.after_id) {
      const afterIndex = models.findIndex(m => m.id === query.after_id);
      if (afterIndex >= 0) {
        models = models.slice(afterIndex + 1);
      }
    }
    
    if (query.before_id) {
      const beforeIndex = models.findIndex(m => m.id === query.before_id);
      if (beforeIndex >= 0) {
        models = models.slice(0, beforeIndex);
      }
    }

    const limit = query.limit || 20;
    const paginatedModels = models.slice(0, limit);
    
    const response: ModelsResponseDto = {
      data: paginatedModels,
      first_id: paginatedModels.length > 0 ? paginatedModels[0].id : null,
      last_id: paginatedModels.length > 0 ? paginatedModels[paginatedModels.length - 1].id : null,
      has_more: models.length > limit
    };

    this.logger.log(`Listed ${paginatedModels.length} models`);

    return response;
  }

  async getModel(modelId: string, requestInfo: Partial<AnthropicRequestLog>): Promise<ModelDto> {
    this.logRequest('GET', `/v1/models/${modelId}`, null, requestInfo);

    const model = mockModels.find(m => m.id === modelId);
    
    if (!model) {
      throw new Error(`Model not found: ${modelId}`);
    }

    this.logger.log(`Retrieved model: ${modelId}`);

    return model;
  }

  // Batches API Methods
  async createBatch(createBatchDto: CreateBatchDto, requestInfo: Partial<AnthropicRequestLog>): Promise<BatchResponseDto> {
    this.logRequest('POST', '/v1/messages/batches', createBatchDto, requestInfo);

    const batchId = AnthropicMockGenerator.generateBatchId();
    const now = new Date().toISOString();
    const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(); // 24小时后过期

    const response: BatchResponseDto = {
      id: batchId,
      type: 'message_batch',
      processing_status: 'in_progress',
      request_counts: {
        processing: createBatchDto.requests.length,
        succeeded: 0,
        errored: 0,
        canceled: 0,
        expired: 0
      },
      created_at: now,
      expires_at: expiresAt,
      ended_at: null,
      results_url: null,
      metadata: createBatchDto.metadata
    };

    this.logger.log(`Created batch: ${batchId} with ${createBatchDto.requests.length} requests`);

    return response;
  }

  async getBatch(batchId: string, requestInfo: Partial<AnthropicRequestLog>): Promise<BatchResponseDto> {
    this.logRequest('GET', `/v1/messages/batches/${batchId}`, null, requestInfo);

    // 随机返回进行中或已完成的批处理
    const isCompleted = Math.random() > 0.5;
    const batch = isCompleted ? { ...mockCompletedBatch, id: batchId } : { ...mockBatch, id: batchId };

    this.logger.log(`Retrieved batch: ${batchId}, status: ${batch.processing_status}`);

    return batch;
  }

  async listBatches(query: ListBatchesQueryDto, requestInfo: Partial<AnthropicRequestLog>): Promise<BatchesResponseDto> {
    this.logRequest('GET', '/v1/messages/batches', null, requestInfo, query);

    // 生成一些 Mock 批处理数据
    const batches = [mockBatch, mockCompletedBatch];
    
    const response: BatchesResponseDto = {
      data: batches,
      first_id: batches.length > 0 ? batches[0].id : null,
      last_id: batches.length > 0 ? batches[batches.length - 1].id : null,
      has_more: false
    };

    this.logger.log(`Listed ${batches.length} batches`);

    return response;
  }

  async cancelBatch(batchId: string, requestInfo: Partial<AnthropicRequestLog>): Promise<BatchResponseDto> {
    this.logRequest('POST', `/v1/messages/batches/${batchId}/cancel`, null, requestInfo);

    const batch = { 
      ...mockBatch, 
      id: batchId, 
      processing_status: 'canceling' as const
    };

    this.logger.log(`Cancelled batch: ${batchId}`);

    return batch;
  }

  // Files API Methods
  async uploadFile(file: Express.Multer.File, purpose: string, requestInfo: Partial<AnthropicRequestLog>): Promise<FileResponseDto> {
    this.logRequest('POST', '/v1/files', { purpose, filename: file.originalname }, requestInfo);

    const fileId = AnthropicMockGenerator.generateFileId();
    const now = new Date().toISOString();

    const response: FileResponseDto = {
      id: fileId,
      type: 'file',
      purpose,
      filename: file.originalname,
      size_bytes: file.size,
      created_at: now
    };

    this.logger.log(`Uploaded file: ${fileId}, size: ${file.size} bytes`);

    return response;
  }

  async listFiles(query: ListFilesQueryDto, requestInfo: Partial<AnthropicRequestLog>): Promise<FilesResponseDto> {
    this.logRequest('GET', '/v1/files', null, requestInfo, query);

    let files = [...mockFiles];
    
    if (query.purpose) {
      files = files.filter(f => f.purpose === query.purpose);
    }

    const limit = query.limit || 20;
    const paginatedFiles = files.slice(0, limit);

    const response: FilesResponseDto = {
      data: paginatedFiles,
      first_id: paginatedFiles.length > 0 ? paginatedFiles[0].id : null,
      last_id: paginatedFiles.length > 0 ? paginatedFiles[paginatedFiles.length - 1].id : null,
      has_more: files.length > limit
    };

    this.logger.log(`Listed ${paginatedFiles.length} files`);

    return response;
  }

  async getFile(fileId: string, requestInfo: Partial<AnthropicRequestLog>): Promise<FileResponseDto> {
    this.logRequest('GET', `/v1/files/${fileId}`, null, requestInfo);

    const file = mockFiles.find(f => f.id === fileId);
    
    if (!file) {
      throw new Error(`File not found: ${fileId}`);
    }

    this.logger.log(`Retrieved file: ${fileId}`);

    return file;
  }

  async getFileContent(fileId: string, requestInfo: Partial<AnthropicRequestLog>): Promise<Buffer> {
    this.logRequest('GET', `/v1/files/${fileId}/content`, null, requestInfo);

    // 返回 Mock 文件内容
    const mockContent = `{"custom_id": "request-1", "params": {"model": "claude-sonnet-4-20250514", "max_tokens": 1024, "messages": [{"role": "user", "content": "Hello"}]}}`;
    
    this.logger.log(`Retrieved file content: ${fileId}`);

    return Buffer.from(mockContent, 'utf-8');
  }

  async deleteFile(fileId: string, requestInfo: Partial<AnthropicRequestLog>): Promise<DeleteFileResponseDto> {
    this.logRequest('DELETE', `/v1/files/${fileId}`, null, requestInfo);

    const response: DeleteFileResponseDto = {
      id: fileId,
      type: 'file',
      deleted: true
    };

    this.logger.log(`Deleted file: ${fileId}`);

    return response;
  }

  // Utility Methods
  private async simulateProcessingDelay(): Promise<void> {
    // 模拟 API 处理延迟 (100-500ms)
    const delay = Math.floor(Math.random() * 400) + 100;
    await new Promise(resolve => setTimeout(resolve, delay));
  }

  private logRequest(
    method: string, 
    path: string, 
    body: any, 
    requestInfo: Partial<AnthropicRequestLog>,
    query?: any
  ): void {
    const log: AnthropicRequestLog = {
      id: uuidv4(),
      timestamp: new Date().toISOString(),
      method,
      path,
      headers: requestInfo.headers || {},
      body,
      query,
      ip: requestInfo.ip || 'unknown',
      userAgent: requestInfo.userAgent,
      apiKey: this.maskApiKey(requestInfo.headers?.['x-api-key'])
    };

    this.requestLogs.push(log);

    // 保持最近1000条日志
    if (this.requestLogs.length > 1000) {
      this.requestLogs.splice(0, this.requestLogs.length - 1000);
    }

    // 打印请求日志
    this.logger.log(`${method} ${path} - IP: ${log.ip} - API Key: ${log.apiKey}`);
    if (body) {
      this.logger.debug(`Request Body:`, JSON.stringify(body, null, 2));
    }
    if (query) {
      this.logger.debug(`Query Params:`, JSON.stringify(query, null, 2));
    }
  }

  private maskApiKey(apiKey?: string): string {
    if (!apiKey) return 'none';
    if (apiKey.length <= 8) return '***';
    return apiKey.substring(0, 4) + '***' + apiKey.substring(apiKey.length - 4);
  }

  // 获取请求日志（用于调试和监控）
  getRequestLogs(limit: number = 100): AnthropicRequestLog[] {
    return this.requestLogs.slice(-limit).reverse();
  }

  // 清空请求日志
  clearRequestLogs(): void {
    this.requestLogs.splice(0);
    this.logger.log('Request logs cleared');
  }

  // 获取代理配置信息
  async getProxyConfig(): Promise<any> {
    const mode = this.proxyConfigService.getProxyMode();
    const copilotConfig = await this.proxyConfigService.getCopilotConfig();
    
    return {
      mode: mode,
      debug: await this.proxyConfigService.isDebugMode(),
      timeout: await this.proxyConfigService.getRequestTimeout(),
      maxRetries: await this.proxyConfigService.getMaxRetries(),
      logRequests: await this.proxyConfigService.shouldLogRequests(),
      logResponses: await this.proxyConfigService.shouldLogResponses(),
      copilot: {
        apiUrl: copilotConfig.apiUrl,
        defaultModel: copilotConfig.defaultModel,
        hasAuthToken: !!copilotConfig.authToken,
        userAgent: copilotConfig.userAgent
      }
    };
  }

  // 切换代理模式
  switchProxyMode(mode: 'mock' | 'copilot'): any {
    // 注意：这里只能返回当前配置，实际的模式切换需要通过环境变量
    const currentMode = this.proxyConfigService.getProxyMode();
    
    this.logger.log(`Proxy mode switch requested: ${currentMode} -> ${mode}`);
    
    return {
      currentMode: currentMode,
      requestedMode: mode,
      message: mode === currentMode 
        ? `Already in ${mode} mode`
        : `To switch to ${mode} mode, set ANTHROPIC_PROXY_MODE=${mode} in environment variables and restart the service`
    };
  }

  // 检查代理健康状态
  async checkProxyHealth(): Promise<any> {
    const mode = this.proxyConfigService.getProxyMode();
    const result: any = {
      mode: mode,
      status: 'healthy',
      timestamp: new Date().toISOString(),
      services: {
        mock: 'healthy',
        forwarding: 'unknown'
      }
    };

    if (mode === ProxyMode.COPILOT) {
      try {
        const forwardingHealth = await this.forwardingService.checkForwardingHealth();
        result.services.forwarding = forwardingHealth.copilotApi === 'reachable' ? 'healthy' : 'unhealthy';
        result.copilotApi = forwardingHealth;
      } catch (error) {
        result.services.forwarding = 'error';
        result.error = error.message;
        result.status = 'degraded';
      }
    }

    this.logger.log(`Proxy health check completed: ${result.status}`);
    
    return result;
  }

  // 配置管理方法
  async getFullProxyConfig(): Promise<any> {
    if (!this.configManagementService) {
      // 简化版配置信息
      return await this.getProxyConfig();
    }
    return await this.configManagementService.getProxyConfig();
  }

  async updateCopilotConfig(updateDto: any): Promise<any> {
    if (!this.configManagementService) {
      return {
        success: false,
        message: 'Configuration management service not available'
      };
    }
    return this.configManagementService.updateCopilotConfig(updateDto);
  }

  async testCopilotConnection(testDto: any): Promise<any> {
    if (!this.configManagementService) {
      return {
        success: false,
        message: 'Configuration management service not available'
      };
    }
    return this.configManagementService.testConnection(testDto);
  }

  getTokenInfo(): any {
    if (!this.configManagementService) {
      return { valid: false, message: 'Configuration management service not available' };
    }
    return this.configManagementService.getTokenInfo();
  }

  async switchMode(mode: 'mock' | 'copilot'): Promise<any> {
    if (!this.configManagementService) {
      return {
        success: false,
        message: 'Configuration management service not available'
      };
    }
    return this.configManagementService.switchMode(mode);
  }

  async refreshToken(): Promise<any> {
    if (!this.configManagementService) {
      return {
        success: false,
        message: 'Configuration management service not available'
      };
    }
    return this.configManagementService.refreshToken();
  }

  async getTokenHealth(): Promise<any> {
    if (!this.configManagementService) {
      return {
        status: 'unavailable',
        message: 'Configuration management service not available'
      };
    }
    return this.configManagementService.getTokenHealth();
  }

  // 设置配置管理服务（避免循环依赖）
  setConfigManagementService(service: any): void {
    this.configManagementService = service;
  }
}